/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package JTCPconnection;

import java.io.*;

/**
 * REV 5:
 * Quick-patched to listen for JSON data instead of newline-terminated strings
 * @author M-R-D
 */
public final class TCPlistener implements Runnable
{
	Thread			_t;
	TCPconnection	_parent;
	BufferedReader	_in;
	boolean			_shuttingDown	= false;
	
	StringBuilder _sb;
	private int _markCounter = 0;
	/** is mark char array '[]' (true) or object '{}' (false) */
	private boolean _markArray = false;

	public TCPlistener(BufferedReader rd, TCPconnection parent)
	{
		_in = rd;
		_parent = parent;
		init();
	}

	private void init()
	{
		_t = new Thread(this);
		_t.start();
	}

	@Override
	public void run()
	{
		try
		{
			/*
			String msg = " ";
			while(msg != null && !_shuttingDown)
			{
			    msg = _in.readLine();
			    if(msg != null)
			    {
			        _parent.receiveMessage(msg);
			    }
			}
			*/
			while(true)
			{
				//while(!_in.ready() && !_shuttingDown)
				//{
					//Thread.sleep(0, 100000);
				//}
				
				if(_shuttingDown) break;
				
				int ch = _in.read();
				
				if(ch == -1)
				{
					_parent.onConnectionLost();
					_shuttingDown = true;
					break;
				}
				
				if(ch > 255)
				{
					System.out.println("char out of range");
				}
				
				if(_markCounter == 0)
				{
					switch(ch)
					{
						case '{':
							_markArray = false;
							haveJSONstart();
							_sb.append('{');
							break;
						case '[':
							_markArray = true;
							haveJSONstart();
							_sb.append('[');
							break;
						default:
							//ignore character: not valid here
							break;
					}
				}
				else
				{
					if(_markArray)
					{
						switch(ch)
						{
							case '[':
								_sb.append('[');
								_markCounter++;
								break;
							case ']':
								_sb.append(']');
								possibleJSONend();
								break;
							default:
								_sb.append((char)ch);
								break;
						}
					}
					else
					{
						switch(ch)
						{
							case '{':
								_sb.append('{');
								_markCounter++;
								break;
							case '}':
								_sb.append('}');
								possibleJSONend();
								break;
							default:
								_sb.append((char)ch);
								break;
						}
					}
				}
			}
		}
		catch (Exception e)
		{
			_parent.onConnectionLost();
		}
	}
	
	private void haveJSONstart()
	{
		_markCounter = 1;
		_sb = new StringBuilder();
	}
	
	private void possibleJSONend()
	{
		_markCounter--;
		
		if(_markCounter == 0)
		{
			String result = _sb.toString();
			_parent.receiveMessage(result);
		}
	}

	/**
	 * Causes the listener to stop (and terminate) when either the currently read char is processed, or, when waiting for new data, within 100 usec.
	 */
	public void stop()
	{
		_shuttingDown = true;
	}
}
